package com.framework.common.utils;


import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import ws.schild.jave.Encoder;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;
import ws.schild.jave.info.MultimediaInfo;
import ws.schild.jave.info.VideoInfo;
import ws.schild.jave.info.VideoSize;
import ws.schild.jave.process.ffmpeg.DefaultFFMPEGLocator;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Map;

/**
 * @author lihanbo
 * @version 1.0
 * @date 2022/2/25 11:47
 */
@Component
@Slf4j
public class FFmpegUtil {

    @PostConstruct
    public void init() {
        //加载ffmpeg工具
        DefaultFFMPEGLocator defaultFFMPEGLocator = new DefaultFFMPEGLocator();
    }

    /**
     * 视频文件转音频文件
     *
     * @param videoPath
     * @param audioPath
     * @return
     */
    public static boolean videoToAudio(String videoPath, String audioPath) {
        File source = new File(videoPath);
        File target = new File(audioPath);

        //Audio Attributes
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        audio.setBitRate(128000);
        audio.setChannels(2);
        audio.setSamplingRate(44100);

        //Encoding attributes
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setOutputFormat("mp3");
        attrs.setAudioAttributes(audio);
        //Encode
        Encoder encoder = new Encoder();
        try {
            encoder.encode(new MultimediaObject(source), target, attrs);
            return true;
        } catch (Exception e) {
            log.error("转mp3异常：" + e.getMessage(), e);
            return false;
        }
    }

    /**
     * 获取视频的基本信息，视频长宽高，视频的大小等
     *
     * @param fileSource
     * @return
     */
    public static Dict getVideoInfo(String fileSource) {
        File source = new File(fileSource);
        //Encoder encoder = new Encoder();
        FileInputStream fis = null;
        FileChannel fc = null;
        Dict dict = null;
        try {
            MultimediaObject MultimediaObject = new MultimediaObject(source);
            MultimediaInfo m = MultimediaObject.getInfo();
            fis = new FileInputStream(source);
            fc = fis.getChannel();
            dict = Dict.create().set("width", m.getVideo().getSize().getWidth())
                    .set("height", m.getVideo().getSize().getHeight())
                    .set("size", fc.size())
                    .set("duration", m.getDuration())
                    .set("format", m.getFormat());
            System.out.println(dict);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != fc) {
                try {
                    fc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fis) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return dict;
    }

    /**
     * 截取视频中某一帧作为图片
     *
     * @param videoPath
     * @param imagePath
     * @return
     */
    public static boolean getVideoProcessImage(String videoPath, String imagePath) {
        File videoSource = new File(videoPath);
        File imageTarget = new File(imagePath);
        MultimediaObject object = new MultimediaObject(videoSource);
        try {
            MultimediaInfo multimediaInfo = object.getInfo();
            VideoInfo videoInfo = multimediaInfo.getVideo();
            Map<String, String> metadata = videoInfo.getMetadata();
            String rotate = metadata.getOrDefault("rotate", "");
            VideoSize vs = videoInfo.getSize();
//            if (rotate) {
//                vs = new VideoSize(videoInfo.getSize().getHeight(), videoInfo.getSize().getWidth());
//            }
            VideoAttributes video = new VideoAttributes();
            video.setCodec("png");
            video.setSize(vs);
            EncodingAttributes attrs = new EncodingAttributes();
            //VideoAttributes attrs = ecodeAttrs.getVideoAttributes().get();
            attrs.setOutputFormat("image2");
            attrs.setDuration(0.01f);//设置转码持续时间（1秒）
            attrs.setVideoAttributes(video);
            Encoder encoder = new Encoder();
            encoder.encode(object, imageTarget, attrs);
            //  C:\Users\ADMINI~1\AppData\Local\Temp\jave\ffmpeg-amd64-3.2.0.exe -i
            //  E:\Download\111.mp4 -t 0.01 -vcodec png -s 1440x720 -movflags faststart -an -f image2 -y
            //  E:\Download\111.png -hide_banner
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * m4r音频格式转换为mp3，audioPath可更换为要转换的音频格式
     *
     * @param audioPath
     * @param mp3Path
     */
    public static void m4rToMp3(String audioPath, String mp3Path) {
        File source = new File(audioPath);
        File target = new File(mp3Path);
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        audio.setBitRate(new Integer(128000));
        audio.setChannels(new Integer(2));
        audio.setSamplingRate(new Integer(44100));
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setOutputFormat("mp3");
        attrs.setAudioAttributes(audio);
        Encoder encoder = new Encoder();
        try {
            encoder.encode(new MultimediaObject(source), target, attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从和视频中提取音频wav
     *
     * @param aviPath
     * @param targetWavPath
     */
    public static void videoExtractAudio(String aviPath, String targetWavPath) {
        File source = new File(aviPath);
        File target = new File(targetWavPath);
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("pcm_s16le");
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setOutputFormat("wav");
        attrs.setAudioAttributes(audio);
        Encoder encoder = new Encoder();
        try {
            encoder.encode(new MultimediaObject(source), target, attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 视频转换为手机可播放的格式
     *
     * @param sourceVideo sourceVideo.avi
     * @param targetVideo targetVideo.3gp
     */
    public static void videoToMobileVideo(String sourceVideo, String targetVideo) {
        File source = new File("source.avi");
        File target = new File("target.3gp");
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libfaac");
        audio.setBitRate(new Integer(128000));
        audio.setSamplingRate(new Integer(44100));
        audio.setChannels(new Integer(2));
        VideoAttributes video = new VideoAttributes();
        video.setCodec("mpeg4");
        video.setBitRate(new Integer(160000));
        video.setFrameRate(new Integer(15));
        video.setSize(new VideoSize(176, 144));
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setOutputFormat("3gp");
        attrs.setAudioAttributes(audio);
        attrs.setVideoAttributes(video);
        Encoder encoder = new Encoder();
        try {
            encoder.encode(new MultimediaObject(source), target, attrs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean silk2mp3(String silkPath, String pcmPath, String mp3Path) {
        boolean bl = silk2Pcm(silkPath, pcmPath);
        if (bl) {
            return pcm2Mp3(pcmPath, mp3Path);
        } else {
            return false;
        }
    }

    /**
     * 解码为pcm格式
     */
    public static boolean silk2Pcm(String silkPath, String pcmPath) {
        Process process = null;
        try {
            String silkv3Path = "";
            String command = "";
            if (FileUtil.isWindows()) {
                silkv3Path = getProPath() + File.separator + "silk-v3-decoder" + File.separator + "windows" + File.separator + "silk_v3_decoder.exe";
                command = "cmd.exe /c " + silkv3Path + " " + silkPath + " " + pcmPath + " -quiet";
            } else {
                silkv3Path = getProPath() + File.separator + "silk-v3-decoder" + File.separator + "converter.sh";
                command = "sh " + silkv3Path + " " + silkPath + " " + pcmPath;
            }
            process = RuntimeUtil.exec(command);
            int i = process.waitFor();
            return i == 0;
        } catch (Exception e) {
            log.error("silk2Pcm异常：" + e.getMessage(), e);
            return false;
        } finally {
            RuntimeUtil.destroy(process);
        }
    }

    /**
     * pcm为MP3格式
     */
    public static boolean pcm2Mp3(String pcm, String mp3) {
        Process process = null;
        try {
            DefaultFFMPEGLocator ffmpeg = new DefaultFFMPEGLocator();
            String command = "";
            if (FileUtil.isWindows()) {
                command = "cmd.exe /c " + ffmpeg.getExecutablePath() + " -y -f s16le -ar 24000 -ac 1 -i " + pcm + " " + mp3;
            } else {
                command = ffmpeg.getExecutablePath() + " -y -f s16le -ar 24000 -ac 1 -i " + pcm + " " + mp3;
            }
            process = RuntimeUtil.exec(command);
            int i = process.waitFor();
            return i == 0;
        } catch (Exception e) {
            log.error("pcm2Mp3异常：" + e.getMessage(), e);
            return false;
        } finally {
            RuntimeUtil.destroy(process);
        }
    }


    public static String getProPath() throws FileNotFoundException {
        File path = new File(ResourceUtils.getURL("classpath:").getPath());
        if (!path.exists()) {
            path = new File("");
        }
        return path.getAbsolutePath();
    }

    public static void main(String[] args) {
//        FFmpegUtil.silk2mp3("D:\\88af7e656f20416fb34118ff22a63dbc.silk"
//                , "D:\\88af7e656f20416fb34118ff22a63dbc.pcm"
//                , "D:\\88af7e656f20416fb34118ff22a63dbc.mp3");
        FFmpegUtil.getVideoProcessImage("E:\\Download\\22222.mp4", "E:\\Download\\22222.png");

    }

}
